// onlyNumbers <?php
/**
 * Only accept Numbers in Input Text
 * By Olivier St-Laurent
 *
 *
 * Usage :
 *
 *      HTML :
 *
 *      <input id="hours" type="text" /> :
 *      <input id="minutes" type="text" />
 *
 *      Javascript :
 *
 *          $('#hours').onlyNumbers({
 *              maxLength : 2,
 *              minValue : 0,
 *              maxValue : 23,
 *              jumpTo : 'minutes'
 *          });
 *          $('#minutes').onlyNumbers({
 *              maxLength : 2,
 *              minValue : 0,
 *              maxValue : 59
 *          });
 *
 *
 *///?>

function getInputTextSelectionRange(input) {
    if ("selectionStart" in input) {
        return {
            start : input.selectionStart,
            end : input.selectionEnd,
            length : input.selectionEnd - input.selectionStart
        };
    }
    var bookmark = document.selection.createRange().getBookmark();
    var selection = input.createTextRange();
    selection.moveToBookmark(bookmark);
    var before = input.createTextRange();
    before.collapse(true);
    before.setEndPoint("EndToStart", selection);
    return {
        start : before.text.length,
        end : before.text.length + selection.text.length,
        length : selection.text.length
    };
}

(function($) {
    $.fn.onlyNumbers = function(options) {
        if (typeof options === 'number') {
            options = {
                maxLength : options
            };
        }
        if (typeof options !== 'object') {
            options = {};
        }
        options = $.extend({
            maxLength : null,
            allowDecimals : false,
            decimalChars : [46, 44],
            minValue : null,
            maxValue : null,
            jumpTo : null,
            jumpKeys : [13, 58, 45, 47, 32],
            acceptActionKeys : [8, 9, 46, 16],
            jumpIfLengthReached : true,
            clickSelect : true,
            debugKeys : false,
            preventPaste : true
        }, options);

        if (options.allowDecimals && typeof options.allowDecimals === 'number' && options.maxLength) {
            options.maxLength = parseInt(+options.maxLength) + 1 + options.allowDecimals;
        }

        $(this).each(function() {
            if (this.tagName.toLowerCase() === 'input') {

                $(this).keypress(function(event) {
                    return $.onlyNumbers(this, event, options);
                });

                if (options.preventPaste) {
                    $(this).bind('paste', function(event) {
                        event.preventDefault();
                        return false;
                    });
                }

                if (options.clickSelect) {
                    $(this).mouseup(function(event) {
                        this.select();
                    });
                }
            }
        });

    };

    $.onlyNumbers = function(elem, event, options) {
        if (options.maxLength === null && options.maxValue) {
            options.maxLength = ('' + options.maxValue).length;
        }
        var k = event.which || event.keyCode;
        if (options.debugKeys) {
            console.log(k);
        }
        var c = '';
        var newStr = elem.value;

        if (options.allowDecimals) {
            for (var i in options.decimalChars) {
                switch (options.decimalChars[i]) {
                    case 44 :
                        newStr = newStr.replace(',', '.');
                        break;
                    case 59 :
                        newStr = newStr.replace(';', '.');
                        break;
                    case 58 :
                        newStr = newStr.replace(':', '.');
                        break;
                    case 45 :
                        newStr = newStr.replace('-', '.');
                        break;
                    case 32 :
                        newStr = newStr.replace(' ', '.');
                        break;
                    case 39 :
                        newStr = newStr.replace('\'', '.');
                        break;
                    case 34 :
                        newStr = newStr.replace('"', '.');
                        break;
                    case 47 :
                        newStr = newStr.replace('/', '.');
                        break;
                    case 95 :
                        newStr = newStr.replace('_', '.');
                        break;
                }
            }
            if (newStr.indexOf('.') === 0) {
                newStr = '0' + newStr;
            }
        }

        var jump = function() {
            if (options.jumpTo) {
                var jumpTo = (typeof options.jumpTo === 'function') ? options.jumpTo(elem) : options.jumpTo;
                jumpTo = $(jumpTo)[0] || document.getElementById(jumpTo);
                if (jumpTo) {
                    setTimeout(function() {
                        jumpTo.focus();
                        jumpTo.select();
                    }, 0);
                } else {
                    setTimeout(function() {
                        $(elem).blur();
                    }, 0);
                }
            }
        };

        if ((k >= 48 && k <= 57) ||
            $.inArray(k, options.acceptActionKeys) != -1 ||
            $.inArray(k, options.jumpKeys) != -1 ||
            (options.allowDecimals && $.inArray(k, options.decimalChars) != -1)) {
            if (k == 46 && !options.allowDecimals) {
                return false;
            }
            if (k >= 48 && k <= 57) {
                c = '' + (+k - 48);
                var selection = getInputTextSelectionRange(elem);
                newStr = newStr.substr(0, selection.start) + '' + c + '' + newStr.substr(selection.end, newStr.length);

                if (options.minValue &&
                    (parseInt(+newStr)) < parseInt(options.minValue) &&
                    (parseInt(+newStr).toFixed(0).length >= (parseInt(+options.minValue).toFixed(0)).length)) {
                    return false;
                }
                if (options.maxValue && (+newStr) > +options.maxValue) {
                    return false;
                }
                if (options.maxLength && newStr.length > options.maxLength) {
                    return false;
                }

                if (!options.allowDecimals && (parseInt(+newStr) * 10) > parseInt(+options.maxValue)) {
                    if (options.jumpIfLengthReached) {
                        jump();
                    }
                    return true;
                }
                if (options.allowDecimals && typeof options.allowDecimals === 'number') {
                    if (newStr.length === (+newStr).toFixed(options.allowDecimals).length) {
                        if (options.jumpIfLengthReached) {
                            jump();
                        }
                        return true;
                    } else if (newStr.length > (+newStr).toFixed(options.allowDecimals).length) {
                        if (options.jumpIfLengthReached) {
                            jump();
                        }
                        return false;
                    }
                }
            }
            if ($.inArray(k, options.jumpKeys) != -1 &&
                (!options.allowDecimals || $.inArray(k, options.decimalChars) == -1)) {
                jump();
                return false;
            }
            if ($.inArray(k, options.acceptActionKeys) == -1 &&
                options.jumpIfLengthReached && (options.maxLength && +newStr.length === +options.maxLength)) {
                jump();
            }
            return true;
        }
        return false;
    };
})(jQuery);
